﻿// ***********************************************************************
// Assembly         : TCPServerSocket
// Author           : yubao
// Created          : 07-18-2014
//
// Last Modified By : yubao
// Last Modified On : 07-29-2014
// ***********************************************************************
// <copyright file="TcpServer.cs" company="www.cnblogs.com/dotcpp">
//     Copyright (c) www.cnblogs.com/dotcpp. All rights reserved.
// </copyright>
// <summary>TCP servver</summary>
// ***********************************************************************
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;

namespace TCPServerSocket
{
    public class TcpServer
    {
        const int NumOfThread = 2;
        public bool Listening { get; private set; }
        public string Ip { get; set; }
        public int ListenPort = 8080;

        private readonly ClientConnectionPool _connectionPool;            //客户端连接池
        private readonly Thread[] _threadTask = new Thread[NumOfThread];  //客户端处理线程
        
        private Thread _listenthread;
        private TcpListener _listen;

        #region 委托
        /// <summary>
        ///收到新的客户端
        /// </summary>
        public Action<ClientHandler> RecvNewClientAction;
        /// <summary>
        /// 失去连接
        /// </summary>
        public Action<ClientHandler> LostClientAction;
        /// <summary>
        /// 接收数据
        /// </summary>
        public Action<string, byte[], int> RecvDataAction;
        #endregion

        public TcpServer()
        {
            Listening = false;
            _connectionPool = new ClientConnectionPool();
        }

        public void StopListen()
        {
            Listening = false;
            for (int i = 0; i < _threadTask.Length; i++)
            {
                if (_threadTask[i] != null && _threadTask[i].IsAlive)
                    _threadTask[i].Join();
            }
            // Close all client connections
            while (_connectionPool.Count > 0)
            {
                ClientHandler client = _connectionPool.Dequeue();
                client.Close();
            }
            _listen.Server.Close();
            _listenthread.Abort();
        }
        public void StartListen()
        {
            if (Listening) return;
            Listening = true;
            for (int i = 0; i < _threadTask.Length; i++)
            {
                _threadTask[i] = new Thread(MainThread);
                _threadTask[i].Start();
            }
            _listen = string.IsNullOrEmpty(Ip) ? new TcpListener(ListenPort) : new TcpListener(IPAddress.Parse(Ip), ListenPort);
            _listen.Start();
            _listenthread = new Thread(ListenThread);
            _listenthread.Start();
        }

        //得到在线IP地址列表
        public IEnumerable<string> GetOnLine()
        {
            lock (_connectionPool.SyncRoot)
            {
                foreach (ClientHandler client in _connectionPool)
                {
                    yield return client.ToString();
                }
            }
        }

        //向指定的IP发送信息
        public void SendMessage(string ipaddress, string message)
        {
            SendMessage(ipaddress, Encoding.Default.GetBytes(message));
        }
        public void SendMessage(string ipaddress, byte[] buffers)
        {
            var client = GetClient(ipaddress);
            if(client != null)
                client.SendMessage(buffers);
        }
        //删除客户端
        public void DelClient(string ipaddress)
        {
            var client = GetClient(ipaddress);
            if (client != null) client.Alive = false;
        }

        private ClientHandler GetClient(string ipaddress)
        {
            lock (_connectionPool.SyncRoot)
            {
                foreach (ClientHandler client in _connectionPool)
                {
                    if (client.ToString() == ipaddress)
                    {
                        return client;
                    }
                }
            }
            return null;
        }

        #region 线程函数
        private void ListenThread()
        {
            while (Listening)
            {
                try
                {
                    TcpClient client = _listen.AcceptTcpClient();
                    var handler = new ClientHandler(client);
                    if (RecvNewClientAction != null)
                        RecvNewClientAction(handler);
                    _connectionPool.Enqueue(handler);
                }
                catch (Exception e)
                {
                }
            }
        }
        private void MainThread()
        {
            while (Listening)
            {
                ClientHandler client = null;
                lock (_connectionPool.SyncRoot)
                {
                    if (_connectionPool.Count > 0)
                        client = _connectionPool.Dequeue();


                    if (client != null)
                    {
                        client.Process(RecvDataAction); // Provoke client
                        if (client.Alive)
                            _connectionPool.Enqueue(client);
                        else
                        {
                            if (LostClientAction != null)
                                LostClientAction(client);
                        }
                    }
                }
                Thread.Sleep(1);
            }
        }
        #endregion
    }
}
